package com.pig4cloud.pigx.contract.schedule;

import com.pig4cloud.pigx.common.customize.redis.utils.RedisUtils;
import com.pig4cloud.pigx.contract.config.contract.ContractConfig;
import com.pig4cloud.pigx.contract.constant.ContractMqConstants;
import com.pig4cloud.pigx.contract.constant.ContractRedisLockConstants;
import com.pig4cloud.pigx.contract.constant.ContractScheduleConstants;
import com.pig4cloud.pigx.contract.mapper.ContractPositionMapper;
import lombok.AllArgsConstructor;
import org.redisson.api.RLock;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Objects;

/**
 * 计算任务发布者
 *
 * @since 2022/8/27 11:33
 */
@Component
@AllArgsConstructor
public class ContractTaskPublisher {

    private final ContractPositionMapper contractPositionMapper;
    private final ContractConfig contractConfig;

    private final RedisUtils redisUtils;
    private final AmqpTemplate rabbit;
    private final MongoTemplate mongo;

    /**
     * 发布 仓位检查保证金触发器 任务
     *
     * @since 2022/9/17 17:18
     */
    @Scheduled(fixedDelay = ContractScheduleConstants.PUBLISH_INTERVAL_POSITION_MARGIN_CHECK_TRIGGER)
    private void publishMarginCheckTask() {
        // 竞争分布式锁
        RLock lock = redisUtils.getLock(ContractRedisLockConstants.PUBLISH_TASK_POSITION_MARGIN_CHECK_TRIGGER, null);
        if (Objects.isNull(lock)) {
            return;
        }

        // 获取最大处理条数
        Integer limit = contractConfig.getPosition().getLimitWhenDispatchMarginCheck();

        // 初始化起始下标、结束下标
        int startIndex = 0;
        int endIndex = startIndex + limit;

		/*
		 从旧到新查询未发送过邮件的当前可用仓位的userIdList，并判断数量
		 <p> 从旧到新查询：考虑到在循环过程中，可能有新增数据
		 */
        List<Long> userIdList;
        while ((userIdList = contractPositionMapper.getMarginCheckUserIdList(startIndex, endIndex)).size() > 0) {
            // 如果有数据，遍历userIdList，发布任务
            userIdList.forEach(userId -> rabbit.convertAndSend(ContractMqConstants.EXCHANGE_FANOUT_CONTRACT_POSITION_MARGIN_CHECK_TRIGGER,
                    null,
                    userId));

            // 如果没有后续记录
            if (userIdList.size() < limit) {
                break;
            }

            // 更新起始下标、结束下标
            startIndex = endIndex;
            endIndex = startIndex + limit;
        }

        // 释放分布式锁
        redisUtils.releaseLock(lock);
    }
}
